#pragma once
#include <chrono>
#include <functional>
#include <memory>
#include <mutex>

namespace zh
{
    using TimerCallbacks = std::function<void()>;
    class Timer;
    using TimerSharedPtr = std::shared_ptr<Timer>;
    using TimerWeakPtr   = std::weak_ptr<Timer>;

    using Clock     = std::chrono::high_resolution_clock;
    using TimePoint = std::chrono::time_point<Clock>;

    class Timer
    {
    public:
        Timer(int delayTime, const TimerCallbacks& callback);
        ~Timer() = default;

        int       getID() const;
        TimePoint getExpiredTime() const;
        bool      isValid() const;

        void run();
        void setInvalid();

        bool operator<(const Timer& other) const
        {
            return m_expiredTime < other.m_expiredTime;
        }

        static int        generateID();
        static int        s_initialID;
        static std::mutex s_mutex;

        enum FlagID
        {
            INVALID_ID = 0
        };

    private:
        int m_id;

        TimePoint      m_expiredTime;
        TimerCallbacks m_callback;
    };
} // namespace zh